package com.ccl.iot;

import java.util.ArrayList;

public abstract class SequenceInvokeList<TYPE> {	
	private Object iSyncLock = new Object();
	
	private String iName = null;
	
	private volatile boolean iRunning = false;
	private volatile boolean iInvokable = true;
	private volatile boolean iInvoking = false;
	
	
	private TYPE iCurItem = null;
	private ArrayList<TYPE> iItems = null;

	public SequenceInvokeList(String aName){
		iName = aName;
	}
	
	public boolean getInvokable(){
		return iInvokable;
	}
	
	public boolean isInvoking(){
		return iInvoking;
	}
	
	public boolean isInvoking(TYPE aItem){
		if (iInvoking){
			return aItem == iCurItem;
		}
		
		return false;
	}
	
	public int getListSize(){
		synchronized(iSyncLock){
			if (iItems != null){
				return iItems.size();
			}
		}
		
		return 0;
	}
	
	public boolean isValidItem(TYPE aItem){
		return aItem != null;
	}
	
	public boolean isSameItem(TYPE aItem1, TYPE aItem2){
		return aItem1 == aItem2;
	}
	
	public boolean addItem(TYPE aItem){
		if (isValidItem(aItem)){
			boolean tExist = false;
			
			synchronized(iSyncLock){
				if (iItems == null){
					iItems = new ArrayList<TYPE>();
				}else{
					if (isSameItem(aItem, iCurItem)){
						return false;
					}else if ((tExist = iItems.contains(aItem)) == false){
						for (int i = iItems.size() - 1; i >= 0; i--){
							if (isSameItem(aItem, iItems.get(i))){
								tExist = true;
								
								break;
							}
						}
					}
				}
				
				if (tExist == false){
					tExist = (iItems.add(aItem) == false);
				}
			}
			
			start();
			
			return (tExist == false);
		}else{
			return false;
		}
	}
	
	public void clear(){
		synchronized(iSyncLock){
			if (iItems != null && iItems.size() > 0){
				iItems.clear();
			}
			
			iRunning = false;
		}
	}
	
	public abstract boolean onInvoke(TYPE aItem);
	
	public void setInvokable(boolean aInvokable){
		synchronized(iSyncLock){
			if (aInvokable != iInvokable){
				iInvokable = aInvokable;
			}
		}
		
		start();
	}
	
	private void start(){
		synchronized(iSyncLock){
			if (iInvokable && iItems != null && iItems.size() > 0){
				if (iRunning == false){
					iRunning = true;
					
					new Thread(new Runnable(){
						@Override
						public void run() {
							TYPE tItem;
							
							Thread.currentThread().setName((iName == null ? "Sequence" : iName) + " invoke list thread");
							
							while(iRunning){
								tItem = null;
								
								synchronized(iSyncLock){
									if (iRunning && iInvokable && iItems != null && iItems.size() > 0){
										tItem = iItems.get(0);
										iCurItem = tItem;
									}else{
										iRunning = false;
										
										break;
									}
								}
								
								if (isValidItem(tItem)){
									iInvoking = true;
									
									if (onInvoke(tItem)){
										iInvoking = false;
										
										synchronized(iSyncLock){
											if (iItems != null){
												iItems.remove(tItem);
											}
										}
									}else{
										iInvoking = false;
									}
								}
								
								if (iCurItem != null){
									iCurItem = null;
								}
							}
						}
					}).start();
					
					/*//TODO 改用线程池操作线程	--(取消)
					ThreadPoolUtils.getInstance().addTask(new Runnable(){
						@Override
						public void run() {
							TYPE tItem;
							
							Thread.currentThread().setName((iName == null ? "Sequence" : iName) + " invoke list thread");
							
							while(iRunning){
								tItem = null;
								
								synchronized(iSyncLock){
									if (iRunning && iInvokable && iItems != null && iItems.size() > 0){
										tItem = iItems.get(0);
										iCurItem = tItem;
									}else{
										iRunning = false;
										
										break;
									}
								}
								
								if (isValidItem(tItem)){
									iInvoking = true;
									
									if (onInvoke(tItem)){
										iInvoking = false;
										
										synchronized(iSyncLock){
											if (iItems != null){
												iItems.remove(tItem);
											}
										}
									}else{
										iInvoking = false;
									}
								}
								
								if (iCurItem != null){
									iCurItem = null;
								}
							}
						}
					});*/
				}
			}			
		}
	}
}
